package com.yunshipei.core.ui.client;

import android.net.Uri;
import android.text.TextUtils;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.yunshipei.core.common.ContentValues;
import com.yunshipei.core.model.DeveloperAppModel;
import com.yunshipei.core.model.InterceptModel;
import com.yunshipei.core.model.MatcherResult;
import com.yunshipei.core.model.OverrideRegexModel;
import com.yunshipei.core.model.XCloudAppModel;
import com.yunshipei.core.net.EnterClient;
import com.yunshipei.core.utils.MimeTypeUtils;
import com.yunshipei.core.utils.YspLogUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public final class FaceWebViewClient extends WebViewClient {

    private static final String ENCODING = "UTF-8";

    private MatcherResult mMatcherResult;

    public FaceWebViewClient(MatcherResult matcherResult) {
        this.mMatcherResult = matcherResult;
    }

    @Override
    public boolean shouldOverrideUrlLoading(final WebView view, String url) {
        view.loadUrl(url);
        return true;
    }

    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        Uri uri = Uri.parse(url);
        if (uri == null) {
            return null;
        }
        String encodePath = uri.getEncodedPath();
        if (TextUtils.isEmpty(encodePath)) {
            return null;
        }

        String type = MimeTypeUtils.getMimeType(view.getContext(),encodePath);

        if (url.startsWith("enterplorer://")) {
            if (mMatcherResult != null) {
                DeveloperAppModel developerAppModel = mMatcherResult.getDeveloperAppModel();
                if (developerAppModel != null) {
                    startLocalLog(url);
                    String proxyServer = developerAppModel.getAppPath();
                    InputStream is = loadProxyStream(proxyServer.substring(0, proxyServer.length() - 2) + uri.getEncodedPath());
                    endLocalLog(url);
                    return new WebResourceResponse(type, ENCODING, is);
                }
            } else {
                startLocalLog(url);
                String fileName = view.getContext().getFilesDir().getPath() + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH + File.separator + uri.getHost() + uri.getEncodedPath();
                try {
                    InputStream is = new FileInputStream(fileName);
                    endLocalLog(url);
                    return new WebResourceResponse(type, ENCODING, is);
                } catch (FileNotFoundException ignored) {
                }
            }
        }

        //=========XCloud2==========
        if (mMatcherResult != null) {
            //资源重载（只重载当前适配包里面的资源）
            String targetOverrideFileName = getOverrideTargetUrl(mMatcherResult.getCloudAppModle(), url);
            if (!TextUtils.isEmpty(targetOverrideFileName)) {
                DeveloperAppModel developerAppModel = mMatcherResult.getDeveloperAppModel();
                if (developerAppModel != null) {
                    startLocalLog(url);
                    String proxyServer = developerAppModel.getAppPath();
                    String resPath = proxyServer + targetOverrideFileName.replace(mMatcherResult.getCloudAppModle().getScope() + File.separator, "");
                    InputStream is = loadProxyStream(resPath);
                    if (is != null) {
                        endLocalLog(url);
                        return new WebResourceResponse(type, ENCODING, is);
                    }
                } else {
                    startLocalLog(url);
                    String fileName = view.getContext().getFilesDir().getPath() + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH + File.separator + targetOverrideFileName;
                    try {
                        InputStream is = new FileInputStream(fileName);
                        endLocalLog(url);
                        return new WebResourceResponse(type, ENCODING, is);
                    } catch (Exception ignored) {
                    }
                }
            }
            //适配包资源替换
            String runtimePath = getRuntimeVersion(mMatcherResult.getCloudAppModle());
            if (encodePath.startsWith(File.separator + runtimePath + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH)) {
                DeveloperAppModel developerAppModel = mMatcherResult.getDeveloperAppModel();
                if (developerAppModel != null) {
                    startLocalLog(url);
                    String proxyServer = developerAppModel.getAppPath();
                    String str = encodePath.substring(encodePath.indexOf("xcloud2json/") + 12);
                    String server = proxyServer + str.replace(mMatcherResult.getCloudAppModle().getScope() + File.separator, "");
                    InputStream is = loadProxyStream(server);
                    if (is != null) {
                        endLocalLog(url);
                        return new WebResourceResponse(type, ENCODING, is);
                    }
                } else {
                    startLocalLog(url);
                    try {
                        String fileName = view.getContext().getFilesDir().getPath() + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH + File.separator + encodePath.substring(encodePath.indexOf("xcloud2json/") + 12);
                        InputStream is = new FileInputStream(fileName);
                        endLocalLog(url);
                        return new WebResourceResponse(type, ENCODING, is);
                    } catch (Exception ignored) {
                    }
                }
            }

            //运行时资源替换
            if (encodePath.startsWith(File.separator + runtimePath)) {
                try {
                    startLocalLog(url);
                    String fileName = view.getContext().getFilesDir().getPath() + encodePath;
                    InputStream is = new FileInputStream(fileName);
                    endLocalLog(url);
                    return new WebResourceResponse(type, ENCODING, is);
                } catch (Exception ignored) {
                }
            }

            //无用资源过滤,如果是双WebView，则自动过滤所有图片资源
            if (!TextUtils.isEmpty(type)) {
                XCloudAppModel xCloudAppModel = mMatcherResult.getCloudAppModle();
                if (shouldFilterResource(xCloudAppModel, url, type)) {
                    try {
                        startLocalLog(url);
                        InputStream is = view.getContext().getAssets().open("empty");
                        endLocalLog(url);
                        return new WebResourceResponse(type, ENCODING, is);
                    } catch (Exception ignored) {
                    }
                }
            }
        }
        return null;
    }

    private void startLocalLog(String url) {
        if (mMatcherResult != null) {
            XCloudAppModel xCloudAppModel = mMatcherResult.getCloudAppModle();
            YspLogUtils.localResStart(url, xCloudAppModel.getScope(), xCloudAppModel.getRuntimeVersion());
        }
    }

    private void endLocalLog(String url) {
        if (mMatcherResult != null) {
            XCloudAppModel xCloudAppModel = mMatcherResult.getCloudAppModle();
            YspLogUtils.localResEnd(url, xCloudAppModel.getScope(), xCloudAppModel.getRuntimeVersion(), "0");
        }
    }

    //是否过滤适配的某个资源
    private boolean shouldFilterResource(XCloudAppModel xCloudAppModel, String url, String type) {
        InterceptModel interceptModel = xCloudAppModel.getInterceptModel();
        if (interceptModel != null) {
            List<String> ignoreResList = interceptModel.getIgnoreResMatcherList();
            for (String matcher : ignoreResList) {
                try {
                    if (url.matches(matcher)) {
                        return false;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            List<String> typeList = interceptModel.getTypes();
            for (String givType : typeList) {
                if (type.contains(givType)) {
                    return true;
                }
            }
        }
        return false;
    }

    //获取运行时的具体信息
    private String getRuntimeVersion(XCloudAppModel xCloudAppModel) {
        String version = "";
        String runtimeVersion = xCloudAppModel.getRuntimeVersion();
        if (!TextUtils.isEmpty(runtimeVersion)) {
            if (runtimeVersion.startsWith("^")) {
                runtimeVersion = runtimeVersion.replace("^", "");
                version = runtimeVersion.split("\\.")[0] + ".+";
            } else {
                version = runtimeVersion;
            }
        }
        return ContentValues.APP_ENGINE_ROOT_PATH + File.separator + version;
    }

    //获取资源重载的目标资源文件
    private String getOverrideTargetUrl(XCloudAppModel xCloudAppModel, String url) {
        List<OverrideRegexModel> listModule = xCloudAppModel.getOverrideModuleList();
        for (OverrideRegexModel module : listModule) {
            List<String> matcherList = module.getMatcherList();
            for (String res : matcherList) {
                try {
                    if (url.matches(res)) {
                        return xCloudAppModel.getScope() + File.separator + module.getTargetURL();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return "";
    }

    //将本地资源替换指向代理服务器
    private InputStream loadProxyStream(String url) {
        OkHttpClient client = EnterClient.getInstances().getManagerClient();
        Request proxyRequest = new Request.Builder().url(url).build();
        try {
            Response response = client.newCall(proxyRequest).execute();
            if (response.code() == 200) {
                return response.body().byteStream();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}